#include <iostream>
using namespace std;

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

#define DATASIZE 20

/* 定义锁 */
pthread_mutex_t g_mutex;
/* 定义条件变量 */
pthread_cond_t g_notempty;
/* 定义条件变量 */
pthread_cond_t g_notFull;

/* 链表节点 */
struct Node
{
    Node(int data, Node *next) : data(data), next(next) {}

    /* 数据域 */
    int data;
    /* 指针域 */
    Node *next;
};

/* 链表头节点 */
Node *g_head = NULL;

/* 链表节点数量 */
int g_size = 0;

/* 生产者线程 */
void *thread_produce(void *arg)
{
    /* 线程分离 */
    pthread_detach(pthread_self());

    /* 休眠10S */
    //sleep(5);

    /* 编号 */
    int number = 1;

    while (1)
    {
#if 0
       Node* newNode = new Node;
       newNode->data = number;
       newNode->next = g_head;
       g_head = newNode;

#else
        /* 加锁 */
        pthread_mutex_lock(&g_mutex);
        while(g_size == DATASIZE)
        {
            /* 阻塞等待条件变量 */
            pthread_cond_wait(&g_notFull,&g_mutex);
        }
        Node *newNode = new Node(number, g_head);
        g_head = newNode;
        g_size++;
        /* 解锁 */
        pthread_mutex_unlock(&g_mutex);

#endif

    
        printf("produce : %ld 生产了 %d 张饼,剩余 %d 张饼\n",pthread_self(),number,g_size);
        number++;
        /* 通知食客 */
        pthread_cond_signal(&g_notempty);

        sleep(1);
        
    }
    /* 退出进程 */
    pthread_exit(NULL);
}

void *thread_consume(void *arg)
{

    /* 线程分离 */
    pthread_detach(pthread_self());
    sleep(20);
    while(1)
    {
        /* 加锁 */
        pthread_mutex_lock(&g_mutex);
        while(g_head == NULL)
        {
            /* 等待条件变量 */
            pthread_cond_wait(&g_notempty,&g_mutex);
        }

        /* 消费 */
        Node * conSumeNode = g_head;
        g_head = g_head->next;


        /* 锁的粒度 */
        /* 解锁 */
        pthread_mutex_unlock(&g_mutex);

        /* 开吃 */
        printf("consume = %ld , eat %d, 还剩 %d 张饼\n",pthread_self(),conSumeNode->data,g_size);
        if(conSumeNode != NULL)
        {
            delete conSumeNode;
            conSumeNode = NULL;
        }
        g_size--;
        sleep(2);
        /* 发信号 */
        //pthread_cond_signal(&g_notFull);
    }

    /* 退出进程 */
    pthread_exit(NULL);
}

int main()
{
     pthread_mutex_init(&g_mutex,NULL);


    /* 创建线程 */
    pthread_t tid1;
    int ret = pthread_create(&tid1, NULL, thread_produce, NULL);
    if (ret != 0)
    {
        perror("thread1 create error");
        exit(1);
    }

    /* 创建线程 */
    pthread_t tid2;
    ret = pthread_create(&tid2, NULL, thread_consume, NULL);
    if (ret != 0)
    {
        perror("thread2 create error");
        exit(1);
    }

    /* 创建线程 */
    pthread_t tid3;
    ret = pthread_create(&tid3, NULL, thread_consume, NULL);
    if (ret != 0)
    {
        perror("thread3 create error");
        exit(1);
    }

    pause();

     pthread_mutex_destroy(&g_mutex);
    return 0;
}